﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PDO.Utilities;

namespace PDO.DataPersistence.Core
{
    /// <summary>
    /// Loads PersistableDataObject types at runtime. 
    /// </summary>
    public class PersistableDataObjectPluginManager : PluginManagerBase<ExtendedPersistableDataObjectAttribute>
    {
        private static PersistableDataObjectPluginManager _currentPDOPluginManager;

        public static PersistableDataObjectPluginManager Current()
        {
            if (_currentPDOPluginManager == null)
            {
                _currentPDOPluginManager = new PersistableDataObjectPluginManager();

                try
                {
                    _currentPDOPluginManager.LoadFromPluginSource();
                    _currentPDOPluginManager.LoadInternalSources();
                }                
                catch (System.IO.FileNotFoundException ex)
                {                    
                    Logger.WriteInformation("Plugins Directory '{0}' not found. No external plugins loaded.", ex.FileName);
                }
                
            }
            return _currentPDOPluginManager;
        }


        protected override void OnValidatePlugin(ExtendedPersistableDataObjectAttribute attrib, Type moduleType, ref bool addToInternalList)
        {
            // TODO : Validate if the object exists through the DAL.
            base.OnValidatePlugin(attrib, moduleType, ref addToInternalList);
        }

        public override Type EnforcedBaseClass
        {
            get
            {
                return typeof(PersistableDataObject);
            }
        }

        /// <summary>
        /// Get Type corresponding to provided extended type name, or null if typeName is not an ExtendedType.
        /// </summary>
        /// <param name="name">Name of Type</param>
        /// <returns>Type or null</returns>
        public Type GetTypeByName(string typeName)
        {
            // MS - Currently we are just spinning through the plugin list here - it could be much more optimal to 
            // load the types into a hash based collection keyed on type.name.
            foreach (PluginInformation<ExtendedPersistableDataObjectAttribute> item in _plugins)
            {
                if (item.PluginImplmentationType.Name == typeName)
                {
                    return item.PluginImplmentationType;
                }
            }
            return null;
        }

        /// <summary>
        /// Get list of Types whose base class name matches the provided type name.
        /// </summary>
        /// <param name="name">Name of base Type</param>
        /// <returns>list of Type</returns>
        public List<Type> GetTypesByBaseType(string baseTypeName)
        {
            List<Type> typeList = new List<Type>();
            foreach (PluginInformation<ExtendedPersistableDataObjectAttribute> item in _plugins)
            {
                if (item.PluginImplmentationType.BaseType.Name == baseTypeName)
                {
                    typeList.Add(item.PluginImplmentationType);
                }
            }
            return typeList;
        }


        /// <summary>
        /// Get Type corresponding to provided extended type full name, or null if name is not an ExtendedType.
        /// </summary>
        /// <param name="name">Full name of Type</param>
        /// <returns>Type or null</returns>
        public Type GetTypeByFullName(string fullName)
        {

            // Check for assembly qualified name, and just use first, namespace/class name portion.
            if (fullName.Contains(","))
            {
                fullName = fullName.Substring(0, fullName.IndexOf(','));
            }

            // MS - Currently we are just spinning through the plugin list here - it could be much more optimal to 
            // load the types into a hash based collection keyed on type.name.
            foreach (PluginInformation<ExtendedPersistableDataObjectAttribute> item in _plugins)
            {
                if (item.PluginImplmentationType.FullName == fullName)
                {
                    return item.PluginImplmentationType;
                }
            }
            return null;
        }
    }
}
